
#include "APP_PLCP_PublicFunction.h"
#include "easyflash.h"
#include "queue.h"

/*****************************************************************

空调按键 id 与状态值
按键 id 按键名称 按键状态 id（从 0 开始）
0 电源 开[电源],关
1 模式 自动[模式],制冷,除湿,送风,制热,
2 温度+ 16[温度+],17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
3 温度- 16[温度-],17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
4 风速 自动[风速],低[风速-],中,高[风速+],强风,飓风,超飓风
5 自动扫风 开,关
6 手动扫风 开,关,1,2,3,4
7 上下扫风 开,关,上,中,下,上中,中下,中-中,上-中,中-下,自动,1,2,3,4,5
8 左右扫风 开,关,左,中,右,左中,中右,左-右,中-中,自动,1,2,3,4,5,6,7
9 强劲 开,关
A 辅热 开,关
B 睡眠 开,关,睡眠 1,睡眠 2,睡眠 3
C 灯光 开,关
D 静音 开,关,静音 1,静音 2
E 节能 开,关
F 换气 开,关
10 健康 开,关
11 定时开 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
12 定时关 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
13 自定义 1 开自然风,关自然风,开清洁,关清洁,开除甲醛,关除甲醛,开净化,关净化,开干燥,关干
燥,开防霉,关防霉,开 3D 风,关 3D 风,开负离子,关负离子
14 自定义 2 开自然风,关自然风,开清洁,关清洁,开除甲醛,关除甲醛,开净化,关净化,开干燥,关干
燥,开防霉,关防霉,开杀菌,关杀菌

e.g.
0 电源 开[电源],关
电源 开 -> id 0; val 0
电源 关 -> id 0; val 1


读取 HLC666 版本
0x92 00 00 00 00 XOR 校验
返回： 
0x06,0x89,0x01,0x00,0x00,0x8F 执行成功 0x06,0xE0,DD,0x00,0x00,XOR 执行失败，DD 为错误 id
 返回的第三字节 0x1 就是版本号

if(有 Device_id)
{
	新建遥控器
	0x80 Device_id hlc666_kfidH hlc666_kfidL 00 XOR 校验
	返回：?? 

	空调状态反馈设置
	0x82 PaHLC666_enable 00 00 00 XOR 校验
	？？
}
else
{
	一键匹配
	0x81 Device_id 0 0 00 XOR 校验
	返回：成功：0x06,0x89,hlc666_kfidH,hlc666_kfidL,0x00,XOR, 失败：0x06,0xE0,DD,0x00,0x00,XOR

	新建遥控器

	空调状态反馈设置
}

发射红外信号
0x86 Device_id Keyid Keyvalue 00 XOR 校验
返回：0x06,0x89,0x00,0x00,0x00,0x8F 执行成功 0x06,0xE0,DD,0x00,0x00,XOR，执行失败，DD 为错误 id


*****************************************************************/
#define HLC666_DIY1				0 //自定义学习型
#define HLC666_AC 				1 //空调
#define HLC666_TV 				2 //电视
#define HLC666_STB 				3 //机顶盒
#define HLC666_DVD 				4 //DVD 播放器
#define HLC666_FAN 				5 //电风扇
#define HLC666_ACL 				6 //空气净化器
#define HLC666_IPTV 			7 //电视盒子
#define HLC666_TYY 				8 //投影仪
#define HLC666_AUD 				9 //音箱
#define HLC666_RSQ 				10 //热水器
#define HLC666_LAMP 			11 //灯
#define HLC666_DIY2 			12 //自定义学习型
#define HLC666_SDJ 				13 //扫地机器人

#define HLC666_CMD_NEW 			0x80
#define HLC666_CMD_PAIRING 		0x81
#define HLC666_CMD_REPORT		0x82
#define HLC666_CMD_KEY_EVENT	0x86
#define HLC666_CMD_VER			0x92

static U16 hlc666_kfid = 0xffff;

/*****************************************************************/
#define HLC666_PARAM_NAME "/hlc666_p"

static void hlc666_param_save(void)
{
	ef_set_env_blob(HLC666_PARAM_NAME, (U8*)&hlc666_kfid, sizeof(hlc666_kfid));
}

void hlc666_param_reset(void)
{
	hlc666_kfid = 0xffff;
	hlc666_param_save();
}

void hlc666_param_recover(void)
{
	if (0 == ef_get_env_blob(HLC666_PARAM_NAME, (U8*)&hlc666_kfid, sizeof(hlc666_kfid), NULL))
	{
		hlc666_param_reset();
	}
}

/*****************************************************************/
static QueueHandle_t hlc666_cmd_send_queue = NULL;
static U8 hlc666_cmd_send_timer = 0xff;

static void hlc666_cmd_send_timer_handler(void)
{
	U8 cmd[6];

	if(hlc666_cmd_send_queue == NULL)
	{
		return;
	}

	if(xQueueReceive(hlc666_cmd_send_queue, cmd, 0) == pdPASS)
	{
		PLCP_uartSend(cmd, 6);
	}
	else{
		APP_StopGenTimer(hlc666_cmd_send_timer);
	}
}

void hlc666_cmd_send(U8* cmd)
{
	if(hlc666_cmd_send_queue == NULL){
		hlc666_cmd_send_queue = xQueueCreate(8, 6);
	}

	if(hlc666_cmd_send_timer == 0xff){
		hlc666_cmd_send_timer = APP_NewGenTimer(250, hlc666_cmd_send_timer_handler);
	}

	if(!APP_CheckGenTimerRunning(hlc666_cmd_send_timer)){
		APP_StartGenTimer(hlc666_cmd_send_timer);
		PLCP_uartSend(cmd, 6);
	}
	else{
		xQueueSendToBack(hlc666_cmd_send_queue, cmd, 500);
	}
}

/***********************************/
static U8 hlc666_send_cmd = 0xff;
U8 hlc666_cmd_xor(U8* msg, U8 msg_len)
{
	U8 xor = 0;

	for(U8 i = 0; i < msg_len; i++) {
		xor ^= msg[i];
	}

	return xor;
}

/***********************************/
// void hlc666_ver(void)
// {
// 	U8 cmd[6];

// 	LOGINFO0(UART_DEBUG, "hlc666_ver\n");

// 	cmd[0] = HLC666_CMD_VER;
// 	cmd[1] = 0;
// 	cmd[2] = 0;
// 	cmd[3] = 0;
// 	cmd[4] = 0;
// 	cmd[5] = hlc666_cmd_xor(cmd, 5);

// 	hlc666_send_cmd = cmd[0];
// 	PLCP_uartSend(cmd, 6);
// }

// void hlc666_ver_process(U8* msg, U8 msg_len)
// {
// 	if(hlc666_send_cmd == HLC666_CMD_VER){
// 		LOGINFO1(UART_DEBUG, "hlc666 ver ack %d\n", msg[2]);
// 	}
// }

/***********************************/
void hlc666_new(void)
{
	U8 cmd[6];

	LOGINFO0(UART_DEBUG, "hlc666_new\n");

	cmd[0] = HLC666_CMD_NEW;
	cmd[1] = HLC666_AC;
	cmd[2] = (hlc666_kfid>>8)&0xff;
	cmd[3] = hlc666_kfid&0xff;
	cmd[4] = 0;
	cmd[5] = hlc666_cmd_xor(cmd, 5);

	hlc666_send_cmd = cmd[0];
	PLCP_uartSend(cmd, 6);
}

// void hlc666_new_ack_process(U8* msg, U8 msg_len)
// {
// 	if(hlc666_send_cmd == HLC666_CMD_NEW){
// 		LOGINFO1(UART_DEBUG, "hlc666_new ack %d\n", msg[2]);
// 	}
// }

/***********************************/
void hlc666_report(void)
{
	U8 cmd[6];

	LOGINFO0(UART_DEBUG, "hlc666_report\n");

	cmd[0] = HLC666_CMD_REPORT;
	cmd[1] = 1;
	cmd[2] = 0;
	cmd[3] = 0;
	cmd[4] = 0;
	cmd[5] = hlc666_cmd_xor(cmd, 5);

	hlc666_send_cmd = cmd[0];
	PLCP_uartSend(cmd, 6);
}

/***********************************/
static U8 hlc666_pairing_timer = 0xff;
static void hlc666_pairing_timer_handler(void)
{
	APP_StopGenTimer(hlc666_pairing_timer);
	if(hlc666_kfid == 0){
		hlc666_kfid = 0xffff;
		hlc666_param_save();
	}
}

void hlc666_pairing(void)
{
	U8 cmd[6];

	LOGINFO0(UART_DEBUG, "hlc666_pairing\n");

	hlc666_kfid = 0;
	if(hlc666_pairing_timer == 0xff){
		hlc666_pairing_timer = APP_NewGenTimer(10000, hlc666_pairing_timer_handler);
		APP_StartGenTimer(hlc666_pairing_timer);
	}
	else{
		APP_StopGenTimer(hlc666_pairing_timer);
		APP_StartGenTimer(hlc666_pairing_timer);
	}

	cmd[0] = HLC666_CMD_PAIRING;
	cmd[1] = HLC666_AC;
	cmd[2] = 0;
	cmd[3] = 0;
	cmd[4] = 0;
	cmd[5] = hlc666_cmd_xor(cmd, 5);

	hlc666_send_cmd = cmd[0];
	PLCP_uartSend(cmd, 6);
}

void hlc666_init(void);
void hlc666_pairing_ack_process(U8* msg, U8 msg_len)
{
	if(hlc666_send_cmd == HLC666_CMD_PAIRING){
		hlc666_kfid = msg[2];
		hlc666_kfid <<= 8;
		hlc666_kfid = msg[3];
		hlc666_param_save();

		hlc666_init();

		LOGINFO1(UART_DEBUG, "hlc666 pairing ack %04x\n", hlc666_kfid);
	}
}

/***********************************/
void hlc666_key_event(U8 key_id, U8 key_val)
{
	U8 cmd[6];

	LOGINFO0(UART_DEBUG, "hlc666_key_event\n");

	cmd[0] = HLC666_CMD_KEY_EVENT;
	cmd[1] = HLC666_AC;
	cmd[2] = key_id;
	cmd[3] = key_val;
	cmd[4] = 0;
	cmd[5] = hlc666_cmd_xor(cmd, 5);

	hlc666_send_cmd = cmd[0];
	hlc666_cmd_send(cmd);
}

/*****************************************************************/
U8 hlc666_msg_rec_handler(U8* msg, U16 msg_len)
{
	if(msg_len == 6 && 
	msg[0] == 0x06 && msg[1] == 0x89 &&
	msg[5] == hlc666_cmd_xor(msg, 5)){

		hlc666_pairing_ack_process(msg, msg_len);

		return 1;
	}

	return 0;
}

static U8 hlc666_init_timer = 0xff;
static void hlc666_init_handler(void)
{
	static U8 hlc666_init_state = 0;

	switch (hlc666_init_state)
	{
	case 0:
		if(hlc666_kfid != 0xffff && hlc666_kfid != 0){
			hlc666_new();
			vTaskDelay(pdMS_TO_TICKS(500));
			
			hlc666_init_state = 1;
		}
		break;
	
	case 1:
		hlc666_report();
		hlc666_init_state = 0;
		APP_StopGenTimer(hlc666_init_timer);
		break;

	default:
		hlc666_init_state = 0;
		break;
	}
}

void hlc666_init(void)
{
	if(hlc666_init_timer == 0xff){
		hlc666_init_timer = APP_NewGenTimer(2000, hlc666_init_handler);
	}
	APP_StartGenTimer(hlc666_init_timer);

	hlc666_param_recover();
}

/*****************************************************************/
void ac_onoff_ctrl(U8 id, U8 on_off)
{
/******************************************
PLCP
0 关, 1 开

HLC666
开[电源],关
**********************************************/
	LOGINFO1(UART_DEBUG, "ac_onoff_ctrl %d\n", on_off);
	hlc666_key_event(0, !on_off);
}

void ac_temp_ctrl(U8 id, U16 temp)
{
/******************************************
HLC666
0:16C, 1:17C ...
**********************************************/
	LOGINFO1(UART_DEBUG, "ac_temp_ctrl %d\n", temp);
	if(temp > 320 || temp < 160){
		LOGINFO0(UART_DEBUG, "ac_temp_ctrl temp err\n");
		return;
	}
	temp = temp/10;
	temp -= 16;	
	hlc666_key_event(2, temp);
}

void ac_wind_ctrl(U8 id, U8 level)
{
/******************************************
PLCP
00 - 自动
01 - 高速
02 - 中速
03 - 中高速
04 - 低速
05 - 中低速
06 - 微风

HLC666
自动[风速],低[风速-],中,高[风速+],强风,飓风,超飓风
**********************************************/
	const U8 wind_table[] = {
		//HLC666		PLCP	
		0,				//0			
		3,				//1
		2,				//2
		2,				//3
		1,				//4
		1,				//5
		1,				//6
	};
	LOGINFO1(UART_DEBUG, "ac_wind_ctrl %d\n", level);
	hlc666_key_event(4, wind_table[level]);
}

void ac_direction_ctrl(U8 id, U8 up_down, u8 left_right)
{
	LOGINFO1(UART_DEBUG, "ac_direction_ctrl %d %d\n", up_down, left_right);
	hlc666_key_event(7, up_down);
	hlc666_key_event(8, left_right);
}

void ac_mode_ctrl(U8 id, U8 mode)
{
/******************************************
PLCP
0，31保留，取值：1-30
0x01 - 制冷
0x02 - 除湿
0x03 - 制热
0x04 - 送风
0x05 - 换气
0x06 - 旁通
0x07 - 省电
0x08 - 速净
0x09 - 舒适
0x0a - 凉风
0x0b - 新风
0x0c - 除霾
0x0d - 除霜
0x0e - 开防冻
0x0f - 关防冻
0x10 - 手动
0x11 - 睡眠
0x12 - 清洗

HLC666
自动[模式],制冷,除湿,送风,制热,
**********************************************/
	const U8 mode_table[] = {
		//HLC666		PLCP	
		0,				//0			
		1,				//1
		2,				//2
		4,				//3
		3,				//4
		3,				//5
	};
	LOGINFO1(UART_DEBUG, "ac_mode_ctrl %d\n", mode);
	if(mode > 5){
		return;
	}
	hlc666_key_event(1, mode_table[mode]);
}

/*****************************************************************/
/*****************************************************************/
void ac_attr_onoff_set(U8 on_off);
U8 ac_attr_onoff_get(void);

#include "PLCP_gpio.h"
#include "PLCP_deviceManage.h"

void ac_attr_reset(void);
void hlc666_param_reset(void);

#define BUTTON_1_PORT					0	
#define BUTTON_1_PIN					8

static U8 button_click_count = 0;
static void button_click(void)
{
	LOGINFO1(UART_DEBUG, "button_click %d\n", button_click_count);

	if(button_click_count == 1){
		ac_attr_onoff_set(!ac_attr_onoff_get());
	}
	else if(button_click_count == 2){
		hlc666_pairing();
	}

	PLCP_SendSearchAck();
}

static void button_long_press(void)
{
	LOGINFO0(UART_DEBUG, "button_long_press\n");
	ac_attr_reset();
	hlc666_param_reset();
	PLCP_RestoreFactorySettings();
	PLCP_SoftReset();
}

static void button_scan(void)
{
	static U8 long_press_counter = 0;
	static U8 button_click_count_timeout = 0xff;

	if(APP_MSE_ProductionTest_GetProductionTestModeFlag()){
		return;
	}

	if(button_click_count_timeout != 0xff){
		if(button_click_count_timeout != 0){
			button_click_count_timeout--;
		}
		else{
			button_click_count_timeout = 0xff;
			button_click();
			button_click_count = 0;
		}
	}

	if(0 == gpio_pin_get_input(BUTTON_1_PORT, BUTTON_1_PIN)){	//press
		long_press_counter++;
		if(long_press_counter >= 50){	//5s
			long_press_counter = 0;
			button_long_press();
		}
	}
	else{														//reless
		if(long_press_counter != 0){
			long_press_counter = 0;
			button_click_count++;
			button_click_count_timeout = 3;
		}
	}
}

void button_init(void)
{
	U8 t_timer;

	//gpio初始化
	SCT_GPIOInitTypeDef SCT_GPIOInitStruct;
	SCT_GPIOInitStruct.GPIO_InCmd = ENABLE;
	SCT_GPIOInitStruct.GPIO_PushPullCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_PullUpCmd = ENABLE;
	SCT_GPIOInitStruct.GPIO_PullDownCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_SchmittCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_HighSpeedCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_DriveLevel = SCT_GPIO_D10MA;

	gpio_init(&SCT_GPIOInitStruct, BUTTON_1_PORT, BUTTON_1_PIN);

	gpio_af_init(BUTTON_1_PORT, BUTTON_1_PIN, 0);

	gpio_pin_set(BUTTON_1_PORT, BUTTON_1_PIN, 1);

	t_timer = APP_NewGenTimer(100, button_scan);
	APP_StartGenTimer(t_timer);
}

/*****************************************************************/
#define LED_1_PORT					0	
#define LED_1_PIN					12

// static U8 led_blink_timer;
// static void led_blink(void)
// {
// 	static U8 led_blink_state = 0xff;
// 	static U8 led_blink_onoff = 0;

// 	LOGINFO1(UART_DEBUG, "led_blink %04x, %04x\n", PLCP_GetDID(), hlc666_kfid);

// 	if(hlc666_kfid == 0){
// 		if(led_blink_state != 0x0f){
// 			led_blink_state = 0x0f;
// 			APP_StopGenTimer(led_blink_timer);
// 			APP_SetGenTimer(led_blink_timer, 250);
// 			APP_StartGenTimer(led_blink_timer);
// 		}		
// 	}
// 	else{
// 		if(PLCP_GetDID() != 0){
// 			if(hlc666_kfid != 0xffff){
// 				if(led_blink_state != 0x11){
// 					led_blink_state = 0x11;
// 					gpio_pin_set(LED_1_PORT, LED_1_PIN, 0);		//off
					
// 				}
// 			}
// 			else{
// 				if(led_blink_state != 0x10){
// 					led_blink_state = 0x10;
// 					gpio_pin_set(LED_1_PORT, LED_1_PIN, 1);		//on
// 				}
// 			}
// 			return;
// 		}
// 		else{
// 			if(hlc666_kfid != 0xffff){
// 				if(led_blink_state != 0x01){
// 					led_blink_state = 0x01;
// 					APP_StopGenTimer(led_blink_timer);
// 					APP_SetGenTimer(led_blink_timer, 1000);
// 					APP_StartGenTimer(led_blink_timer);
// 				}
// 			}
// 			else{
// 				if(led_blink_state != 0x00){
// 					led_blink_state = 0x00;
// 					APP_StopGenTimer(led_blink_timer);
// 					APP_SetGenTimer(led_blink_timer, 3000);
// 					APP_StartGenTimer(led_blink_timer);
// 				}
// 			}
// 		}
// 	}

// 	led_blink_onoff = !led_blink_onoff;
// 	gpio_pin_set(LED_1_PORT, LED_1_PIN, led_blink_onoff);
// }

void led_init(void)
{
	SCT_GPIOInitTypeDef SCT_GPIOInitStruct;
	SCT_GPIOInitStruct.GPIO_InCmd = ENABLE;
	SCT_GPIOInitStruct.GPIO_PushPullCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_PullUpCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_PullDownCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_SchmittCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_HighSpeedCmd = DISABLE;
	SCT_GPIOInitStruct.GPIO_DriveLevel = SCT_GPIO_D10MA;
	gpio_init(&SCT_GPIOInitStruct, LED_1_PORT, LED_1_PIN);
	gpio_af_init(LED_1_PORT, LED_1_PIN, 0);
	gpio_pin_set(LED_1_PORT, LED_1_PIN, 1);

	// SCT_GPIOInitTypeDef SCT_GPIOInitStruct;
	// SCT_GPIOInitStruct.GPIO_InCmd = DISABLE;
	// SCT_GPIOInitStruct.GPIO_PushPullCmd = ENABLE;
	// SCT_GPIOInitStruct.GPIO_PullUpCmd = DISABLE;
	// SCT_GPIOInitStruct.GPIO_PullDownCmd = DISABLE;
	// SCT_GPIOInitStruct.GPIO_SchmittCmd = DISABLE;
	// SCT_GPIOInitStruct.GPIO_HighSpeedCmd = DISABLE;
	// SCT_GPIOInitStruct.GPIO_DriveLevel = SCT_GPIO_D10MA;

	// gpio_init(&SCT_GPIOInitStruct, LED_1_PORT, LED_1_PIN);

	// gpio_af_init(LED_1_PORT, LED_1_PIN, 0);

	// gpio_pin_set(LED_1_PORT, LED_1_PIN, 1);

	// led_blink_timer = APP_NewGenTimer(1000, led_blink);
	// APP_StartGenTimer(led_blink_timer);
}

// void led_ctrl(U8 id, U8 on_off)
// {
// 	gpio_pin_set(LED_1_PORT, LED_1_PIN, on_off);
// }

